/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import sun.misc.Unsafe;

/**
 * 提供了一个框架来实现阻塞锁和依赖于先进先出(FIFO)等待队列的相关同步器(信号量、事件等)。
 * 这个类被设计为大多数依赖于单个原子int值来表示状态的同步器的有用基础。
 * 子类必须定义改变这种状态的受保护方法，这些方法根据对象的获取或释放，定义状态的含义。
 * 
 * 有了这些，这个类中的其他方法将执行所有的排队和阻塞机制。
 * 子类可以维护其他状态字段，但是只有使用getState、setState和
 * compareAndSetState方法进行原子更新的int值才会被同步跟踪。
 *
 * <p>子类应该定义为非公共的内部帮助类，用于实现其外围类的同步属性。
 * 类AbstractQueuedSynchronizer没有实现任何同步接口。
 * 相反，它定义了像acquireInterruptibly这样的方法，
 * 这些方法可以被具体的锁和相关的同步器适当地调用，来实现它们的公共方法。
 *
 * <p>这个类支持默认的独占模式和共享模式。
 * 当以独占模式获取时，其他线程尝试的获取将无法成功。多线程共享模式获取可能(但不一定)成功。
 * 这个类并不“理解”这些区别，除非从机制上讲，
 * 当共享模式获取成功时，下一个等待线程(如果存在)也必须确定它是否也可以获取。
 * 
 * 在不同模式中等待的线程共享相同的FIFO队列。
 * 通常，实现子类只支持其中一种模式，但是这两种模式都可以发挥作用，例如在ReadWriteLock中。
 * 只支持排他模式或仅支持共享模式的子类不需要定义支持未使用模式的方法。
 *
 * <p>这个类定义了一个嵌套ConditionObject类作为Condition的实现，由子类支持独占模式，
 * 方法isHeldExclusively报告同步是否只对当前线程持有,方法release与当前调用getState值，完全释放该对象,
 * 并acquire,鉴于这个保存的状态值,最终该对象恢复到以前被获得的状态。
 * 
 * 没有AbstractQueuedSynchronizer方法创建这样的条件，所以如果不能满足这个约束，就不要使用它。
 * 当然，ConditionObject的行为取决于它的同步器实现的语义。
 *
 * <p>该类为内部队列提供了检查、检测和监视方法，也为条件对象提供了类似的方法。
 * 可以根据需要使用AbstractQueuedSynchronizer将它们的同步机制导出到类中。
 *
 * <p>此类的序列化仅存储底层原子的integer维护状态，因此反序列化的对象具有空线程队列。
 * 要求可序列化的典型子类将定义一个readObject方法，在反序列化时将其恢复到已知的初始状态。
 *
 * <h3>使用</h3>
 *
 * <p>要使用这个类作为同步器的基础，可以使用getState, setState和/或
 * compareAndSetState检查和/或修改同步状态，重新定义以下方法:
 *
 * <ul>
 * <li> {@link #tryAcquire}
 * <li> {@link #tryRelease}
 * <li> {@link #tryAcquireShared}
 * <li> {@link #tryReleaseShared}
 * <li> {@link #isHeldExclusively}
 * </ul>
 *
 * 默认情况下，这些方法都会抛出UnsupportedOperationException。
 * 这些方法的实现必须是内部线程安全的，通常应该是短的，而不是阻塞的。
 * 定义这些方法是使用该类的唯一支持的方法。所有其他方法都声明为final，因为它们不能被独立更改。
 *
 * <p>您可能还会发现从AbstractOwnableSynchronizer继承的方法对于跟踪拥有独占同步器的线程很有用。
 * 我们鼓励您使用它们——这使监视和诊断工具能够帮助用户确定哪些线程持有锁。
 *
 * <p>即使这个类基于内部的FIFO队列，它也不会自动执行FIFO获取策略。
 * 独占同步的核心形式是:
 *
 * <pre>
 * Acquire:
 *     while (!tryAcquire(arg)) {
 *        <em>enqueue thread if it is not already queued</em>;
 *        <em>possibly block current thread</em>;
 *     }
 *
 * Release:
 *     if (tryRelease(arg))
 *        <em>unblock the first queued thread</em>;
 * </pre>
 *
 *  (共享模式类似，但可能涉及级联信号。)
 *
 * <p id="barging">因为在入队前，调用acquire的检查，一个新acquire的线程，可能会先于其他被阻塞和排队的线程。
 * 但是，如果需要的话，你可以定义tryAcquire和/或tryAcquireShared
 * 来通过内部调用一个或多个inspection方法来禁用闯入，从而提供一个公平的FIFO获取顺序。
 * 
 * 特别是，大多数公平同步器可以定义tryAcquire来返回false，如果hasQueuedPredecessors
 * (一个专门为公平同步器使用的方法)返回true。其他的变化也是可能的。
 *
 * <p>缺省的抢占(也称为贪心、放弃和保护避免)策略的吞吐量和可伸缩性通常是最高的。
 * 虽然这不能保证公平或无饥饿，但允许较早队列的线程在较晚队列的线程之前重新竞争，并且每次重新竞争对进入的线程都有一个不偏的成功机会。
 * 此外，虽然acquire在通常意义上不会“旋转”，但它们可能在阻塞之前执行多次调用tryAcquire并穿插其他计算。
 * 
 * 当独占同步只是短暂地保持时，这就提供了旋转的大部分好处，而当独占同步不被保持时，就没有了大部分的责任。
 * 如果需要的话，你可以通过前面的调用来获取具有“fast-path”检查的方法，
 * 可能是预先检查hasContended 和/或hasQueuedThreads，以便只在同步器不可能竞争的情况下才这样做。
 *
 * <p>这个类通过专门化同步器的使用范围，为同步提供了高效和可伸缩的基础，
 * 这些同步器可以依赖于int状态、获取和释放参数，以及内部的FIFO等待队列。
 * 如果这还不够，您可以使用原子类，您自己定制的java.util.Queue队列，LockSupport阻塞支持，从较低的级别构建同步器。
 *
 * <h3>使用样例</h3>
 *
 * <p>这是一个不可重入的互斥锁类，它的值为0表示解锁状态，1表示锁定状态。
 * 虽然不可重入锁并不严格要求记录当前的拥有者线程，但这个类无论如何都会这样做，让使用更容易监视。
 * 它也支持条件和暴露的仪器方法之一:
 *
 *  <pre> {@code
 * class Mutex implements Lock, java.io.Serializable {
 *
 *   // Our internal helper class
 *   private static class Sync extends AbstractQueuedSynchronizer {
 *     // Reports whether in locked state
 *     protected boolean isHeldExclusively() {
 *       return getState() == 1;
 *     }
 *
 *     // Acquires the lock if state is zero
 *     public boolean tryAcquire(int acquires) {
 *       assert acquires == 1; // Otherwise unused
 *       if (compareAndSetState(0, 1)) {
 *         setExclusiveOwnerThread(Thread.currentThread());
 *         return true;
 *       }
 *       return false;
 *     }
 *
 *     // Releases the lock by setting state to zero
 *     protected boolean tryRelease(int releases) {
 *       assert releases == 1; // Otherwise unused
 *       if (getState() == 0) throw new IllegalMonitorStateException();
 *       setExclusiveOwnerThread(null);
 *       setState(0);
 *       return true;
 *     }
 *
 *     // Provides a Condition
 *     Condition newCondition() { return new ConditionObject(); }
 *
 *     // Deserializes properly
 *     private void readObject(ObjectInputStream s)
 *         throws IOException, ClassNotFoundException {
 *       s.defaultReadObject();
 *       setState(0); // reset to unlocked state
 *     }
 *   }
 *
 *   // The sync object does all the hard work. We just forward to it.
 *   private final Sync sync = new Sync();
 *
 *   public void lock()                { sync.acquire(1); }
 *   public boolean tryLock()          { return sync.tryAcquire(1); }
 *   public void unlock()              { sync.release(1); }
 *   public Condition newCondition()   { return sync.newCondition(); }
 *   public boolean isLocked()         { return sync.isHeldExclusively(); }
 *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
 *   public void lockInterruptibly() throws InterruptedException {
 *     sync.acquireInterruptibly(1);
 *   }
 *   public boolean tryLock(long timeout, TimeUnit unit)
 *       throws InterruptedException {
 *     return sync.tryAcquireNanos(1, unit.toNanos(timeout));
 *   }
 * }}</pre>
 *
 * <p>这里有一个类似于CountDownLatch类，只是它只需要一个信号来触发。
 * 因为latch是非排他的，所以它使用shared acquire和release方法。
 *
 *  <pre> {@code
 * class BooleanLatch {
 *
 *   private static class Sync extends AbstractQueuedSynchronizer {
 *     boolean isSignalled() { return getState() != 0; }
 *
 *     protected int tryAcquireShared(int ignore) {
 *       return isSignalled() ? 1 : -1;
 *     }
 *
 *     protected boolean tryReleaseShared(int ignore) {
 *       setState(1);
 *       return true;
 *     }
 *   }
 *
 *   private final Sync sync = new Sync();
 *   public boolean isSignalled() { return sync.isSignalled(); }
 *   public void signal()         { sync.releaseShared(1); }
 *   public void await() throws InterruptedException {
 *     sync.acquireSharedInterruptibly(1);
 *   }
 * }}</pre>
 *
 * @since 1.5
 * @author Doug Lea
 */
public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {

    private static final long serialVersionUID = 7373984972572414691L;

    /**
     * 创建一个初始同步状态为零的新的AbstractQueuedSynchronizer实例。
     */
    protected AbstractQueuedSynchronizer() { }

    /**
     * 等待队列节点类。
     *
     * <p>
     * 等待队列是“CLH”(Craig、Landin和hagersten)锁队列的变体。
     * CLH锁通常用于自旋锁。相反，我们将它们用于阻塞同步器，
     * 但使用相同的基本策略，即在其节点的前驱中保存关于线程的一些控制信息。
     * 
     * 每个节点中的“status”字段跟踪线程是否应该阻塞。
     * 当它的前驱释放时，一个节点就被唤醒了。
     * 
     * 否则，队列中的每个节点都充当特定通知样式的监视器，它持有单个等待线程。
     * status字段不控制线程是否被授予锁等等。
     * 如果线程在队列的第一个位置，它可能会尝试acquire。
     * 但是第一并不能保证成功，它只是给了你竞争的权利。
     * 所以当前释放的竞争者线程可能需要重新等待。
     *
     * <p>要进入CLH锁的队列，您需要将其作为新的尾部，进行原子拼接。
     * 要退出队列，只需设置head字段。
     * <pre>
     *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     * </pre>
     *
     * <p>插入CLH队列只需要在“tail”上进行一个原子操作，因此有一个简单的原子点来划分从未排队到排队。
     * 类似地，脱队列只涉及更新“头”。
     * 然而，节点需要做更多的工作来确定谁是它们的后继节点，部分原因是要处理由于超时和中断而可能发生的取消。
     *
     * <p>“prev”链接(在原始CLH锁中不使用)，主要用于处理取消操作。
     * 如果一个节点被取消，它的后继节点(通常)会重新链接到一个未被取消的前节点。
     * 关于旋锁的类似力学解释，请参阅Scott和Scherer的论文://www.cs.rochester.edu/u/scott/synchronization/
     *
     * <p>我们也使用“下一个”链接去执行阻塞机制。
     * 每个节点的线程id保存在自己的节点中，
     * 因此predecessor通过遍历next链接来确定下一个节点是哪个线程，从而向下一个节点发出唤醒信号。
     * 确定后继节点必须避免与新排队的节点竞争，以设置它们的前一个节点的“next”字段。
     * 当一个节点的后续节点显示为空时，可以通过从原子更新的“tail”往回检查来解决这个问题。
     * (或者，换句话说，下一个链接是一种优化，所以我们通常不需要向后扫描。)
     *
     * <p>取消为基本算法引入了一些保守性。
     * 因为我们必须轮询其他节点的取消，我们可能会忽略一个被取消的节点是在我们前面还是后面。
     * 这是通过在取消时总是取消后继来处理的，允许它们稳定在新的前驱上，
     * 除非我们能够确定将承担此责任的未取消的前驱。
     *
     * <p>CLH队列需要一个虚拟头节点来启动。
     * 但我们不会在建设中创造它们，因为如果没有竞争，那将是浪费精力。
     * 相反，在第一次争用时构造节点并设置头和尾指针。
     *
     * <p>等待条件的线程使用相同的节点，但使用额外的链接。
     * 条件只需要在简单(非并发)的链接队列中链接节点，因为它们只在独占持有时才被访问。
     * 在await过程中，一个节点被插入到条件队列中。收到信号后，节点被转移到主队列。
     * status字段的特殊值用于标记节点所在的队列。
     *
     * <p>感谢Dave Dice、Mark Moir、Victor Luchangco、BillScherer和Michael Scott，
     * 以及jsr -166专家组的成员，为本课程的设计提供了有帮助的想法、讨论和批评。
     */
    static final class Node {
        /** 标记，指示一个节点正在共享模式下等待 */
        static final Node SHARED = new Node();
        /** 标记，指示节点正在独占模式下等待 */
        static final Node EXCLUSIVE = null;

        /** waitStatus值表示线程已取消 */
        static final int CANCELLED =  1;
        /** waitStatus的值，表示后继线程需要被释放 */
        static final int SIGNAL    = -1;
        /** waitStatus值，表示线程正在等待条件 */
        static final int CONDITION = -2;
        /**
         * waitStatus值，指示下一个被获取的应该无条件传播
         */
        static final int PROPAGATE = -3;

        /**
         * Status字段，只接受值:
         *   SIGNAL:     这个节点的后继节点被阻塞(或即将被阻塞)(通过park)，所以当前节点必须在释放或取消时，解锁后继节点。
         *               为了避免竞争，acquire方法必须首先表明它们需要一个signal，然后重试原子获取，然后在失败时阻塞。
         *               
         *   CANCELLED:  该节点因超时或中断而被取消。
         *               节点永远不会离开这个状态。
         *               特别是，一个被取消节点的线程永远不会再次阻塞。
         *               
         *   CONDITION:  线程由于阻塞，进入等待状态。
         *   			  该节点当前在条件队列中。它将不会被用作同步队列节点，直到状态在某个时间点将被设置为0。
         *               (这里使用这个值与字段的其他用途无关，只是简化了机制。)
         *               
         *   PROPAGATE: 处于共享模式下， 下一次的acquire需要无条件传播。
         *   			   一个releaseShared应该传播到其他节点。
         *               这被设置为(仅针对头节点)在doReleaseShared，以确保传播继续，即使其他操作已经介入。
         *               
         *   0:          以上值都不是
         *
         * 数值按数字排列以简化使用。非负值意味着节点不需要信号。
         * 所以，大多数代码不需要检查特定的值，只需要检查符号。
         * 
         * 对于正常同步节点，该字段初始化为0;
         * 对于条件节点，该字段初始化为CONDITION。
         * 它可以使用CAS(或者在可能的情况下，使用无条件的volatile写操作)进行修改。
         */
        volatile int waitStatus;

        /**
         * 链接到前节点，当前节点/线程用于检查waitStatus。
         * 在排队时分配，在退出排队时为空(为了GC)。
         * 同样的，在取消前一个节点时，我们会在找到一个未取消的节点时短路，
         * 因为头节点永远不会被取消:
         * 一个节点只有在成功获取后才会成为头节点。
         * 被取消的线程永远不会成功获取，并且一个线程只会取消自己，而不会取消任何其他节点。
         */
        volatile Node prev;

        /**
         * 链接的后续节点，当前节点/线程释放时，解锁的节点。
         * 在排队时分配，绕过被取消的前驱时调整，并在离开队列时清空(为了GC)。
         * 
         * enq操作直到关联操作完成后才会分配前驱的next字段，所以看到一个空的下一个字段并不一定意味着node在队列的末尾。
         * 然而，如果next字段看起来是空的，我们可以从尾部扫描prev的重复检查。
         * 取消节点的next字段被设置为节点本身，而不是null，以便isOnSyncQueue更容易操作。
         */
        volatile Node next;

        /**
         * 进入该节点队列的线程。构造时初始化，使用后为空。
         */
        volatile Thread thread;

        /**
         * 链接到等待条件的下一个节点，或特殊值SHARED。
         * 因为条件队列只有在独占模式下才能被访问，所以我们只需要一个简单链接的队列来在节点等待条件时容纳它们。
         * 然后，它们被转移到队列中进行获取。
         * 而且由于条件只能是排他的，我们通过使用特殊值来指定共享模式。
         * 
         * nextWaiter成员则是用来表明当前node的线程是想要获取共享锁还是独占锁。注意，这个成员只是这个作用，不是用来连接双向链表的
         */
        Node nextWaiter;

        /**
         * 如果节点在共享模式下等待，则返回true。
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        /**
         * 返回上一个节点，如果为null则抛出NullPointerException。
         * 当前任不能为空时使用。空检查可以被省略，但是存在帮助VM。
         *
         * @return the predecessor of this node
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // 用于建立初始头或共享标记
        }

        Node(Thread thread, Node mode) {     // addWaiter使用
        	// 调用的addWaiter(Node.EXCLUSIVE)，然后会调用下面的这版构造器。
        	// 由此可见，刚放到队尾的node，它的nextWaiter肯定为null，它的waitStatus为0（默认初始化）。
        	//  static final Node EXCLUSIVE = null;
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // Condition使用
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

    /**
     * 等待队列的头，延迟初始化。
     * 除了初始化，它只能通过setHead方法进行修改。
     * 注意:如果head存在，它的waitStatus保证不会被取消。
     * head如果被初始化了，enq方法中就是一个new Node()，作为dummy头，真正的等待队列头是head.next！
     * 节点获取锁后，调用sethead(自己)，然后设置自己的thread和prev为null，相当于一个new Node！
     * 
     * AQS中已经为我们实现了一个FIFO的等待队列，它是一个双向链表。
     * 由于同步器的state一般不能让所有线程同时获得，所以将这些需要暂时等待的线程包装成一个节点放到队列中去，
     * 当获取state的条件满足时，会将这个节点内的线程唤醒，以便它接下来去尝试获取state。
     * 
     * head和tail都是AQS的成员，分别代表队列的头和尾，通过持有这两个成员，相当于AQS也持有了这个队列。
     * 注意head节点作为一个dummy node，它的thread成员一定为null。
     * head节点的thread成员为null，可以理解为将它的thread成员放到AQS的exclusiveOwnerThread属性上去了，所以它的thread成员为null。
     * 即使等待线程只有一个，等待队列中的节点个数也肯定是2个，因为第一个节点总是dummy node。
     */
    private transient volatile Node head;

    /**
     * 等待队列的尾部，延迟初始化。
     * 修改方法仅仅通过enq方法，增加了新的等待节点。
     */
    private transient volatile Node tail;

    /**
     * 同步状态。
     * 
     * 同步器有一个state，它代表着当前同步器的状态，它是整个AQS的核心属性。
     * 我们平时使用的JUC框架下的常用类比如ReentrantLock，其实它们的方法就是在设置和改变这个state。
     * 而之前说的子类需要实现的方法，简单的说，它的实现逻辑也就是在设置和改变这个state。
     * 
     * 独占锁，当state为0时，代表没有线程持有锁。
     * 当state为1时，代表有线程持有锁。
     * 当state>1时，代表有线程持有该锁，并且重入过该锁。
     * 所以state是否为0，可以作为判断是否有线程持有该独占锁的标准。
     */
    private volatile int state;

    /**
     * 返回同步状态的当前值。该操作具有volatile读的内存语义。
     * 
     * @return current state value
     */
    protected final int getState() {
        return state;
    }

    /**
     * 设置同步状态的值。该操作具有volatile写的内存语义。
     * 
     * @param newState the new state value
     */
    protected final void setState(int newState) {
        state = newState;
    }

    /**
     * 如果当前状态值等于预期值，则自动将同步状态设置为给定的updated值。
     * 该操作具有volatile读写的内存语义。
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that the actual
     *         value was not equal to the expected value.
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // 参见下面的本质的设置来支持这一点
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    // 队列工具方法

    /**
     * 旋转而不是使用有时间限制的阻塞的纳秒数。
     * 粗略的估计足以在很短的超时时间内提高响应性。
     */
    static final long spinForTimeoutThreshold = 1000L;

    /**
     * 将节点插入队列，必要时进行初始化。见上图。
     * 
     * @param node the node to insert
     * @return node's predecessor
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // 必须初始化
            	// 进入if (t == null)分支，tail为null，说明队列为空，head肯定也为null。然后尝试CAS设置head成员。
            	// 注意，如果队列从来没有初始化过（head、tail为null），那么这个循环至少得执行两次，
            	// 第一次给队列新建一个空node，第二次进if (t != null)的else分支，把参数node放在空node的后面。
            	// 根据上一条可知，就算只有一个线程入队，入队完毕后队列将有两个node，第一个node称为dummy node，因为它的thread成员为null；
            	// 第二个node才算是实际意义的队头，它的thread成员不为null。
            	
            	// 新建的是空node，它的所有成员都是默认值。thread成员为null，waitStatus为0。之后你会发现，队尾node的waitStatus总是0，因为默认初始化。
            	// compareAndSetHead作为一个CAS操作只有一个参数，是因为它的实现是unsafe.compareAndSwapObject(this, headOffset, null, update);。
            	// compareAndSetHead的CAS操作也可能失败，当队列为空时，两个线程同时执行到enq。

                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
            	// 进入if (t == null)的else分支，tail不为null，说明队列至少有一个dummy node，head肯定也不为null。
            	// 先令node的prev指向tail，但只有CAS设置node为tail成功后，才会将tail的next指向node，才会将双向链表的指针都正确完成指向。
            	// compareAndSetTail(t, node)可能失败，当多个线程都执行到了node.prev = t这里。
            	
            	// enq的尾分叉：如果存在很多个线程都刚好执行到了node.prev = t这里，那么CAS失败的线程不能成功入队，此时它们的prev还暂时指向的旧tail。
            	// tail <- thread1
            	//       <- thread2
            	// tail <-> thread1
            	//       <-   thread2
            	// tail <-> thread1 <-> thread2
            	// prev的有效性：从上图第1步可以看到，此时线程1的node已经是成功放到队尾了，但此时队列却处于一个中间状态，前一个node的next还没有指向队尾呢。
            	// 此时，如果另一个线程如果通过next指针遍历队列，就会漏掉最后那个node；但如果另一个线程通过tail成员的prev指针遍历队列，就不会漏掉node了。
            	// prev的有效性也解释了AQS源码里遍历队列时，为什么常常使用tail成员和prev指针来遍历，比如你看unparkSuccessor。
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                	// 这个循环只有在compareAndSetTail(t, node)成功时才会退出循环，这就保证了enq最终肯定能将参数node放到队尾。
                	// 简单总结就是：enq利用了自旋（循环）和CAS操作，保证了node放到队尾。
                    t.next = node;
                    return t;
                }
            }
        }
    }

    /**
     * 为当前线程和给定模式创建并进入节点队列。
     * 
     * 既然执行到了addWaiter，说明当前线程第一次执行tryAcquire时失败了。
     * 既然获取锁失败了，那么就需要将当前线程包装一个node，放到等待队列的队尾上去，以后锁被释放时别人就会通过这个node来唤醒自己。
     * 
     * 不管是提前return，还是执行完enq再return，当return时，已经是将代表当前线程的node放到队尾了。注意，返回的是，代表当前线程的node。
     *
     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
     * @return the new node
     */
    private Node addWaiter(Node mode) {
    	//设置node的线程和模式
    	// 刚放到队尾的node，它的nextWaiter肯定为null，它的waitStatus为0（默认初始化）。
        Node node = new Node(Thread.currentThread(), mode);
        // 使用enq的快捷方法，如果CAS操作失败，才会去执行enq 
        // 尝试插入队尾
        Node pred = tail;
        if (pred != null) {
        	// 如果队列不为空
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        // 执行到这里，有两种情况：
        // 1.队列为空。head和tail成员从来没有初始化过
        // 2.CAS操作失败。当执行compareAndSetTail时，tail成员已经被修改了
        enq(node);
        return node;
    }

    /**
     * 将队列头设为node，从而退出队列。仅被acquire方法调用。
     * 为了gc和抑制不必要的信号和遍历，也将未使用的字段置空。
     *
     * @param node the node
     */
    private void setHead(Node node) {
        head = node;
        node.thread = null;
        node.prev = null;
    }

    /**
     * 唤醒节点的后续节点(如果存在的话)。
     * 调用release，releaseShared,cancelAcquire时，调用此方法
     *
     * @param node the node
     */
    private void unparkSuccessor(Node node) {
        /*
         * 一般为SIGNAL，然后将其设置为0.
         * 但允许这次CAS操作失败
         * 
         * 首先会尝试设置状态从小于0变成0。
         * 一般可以这样认为，如果head的状态为0，代表head后继线程即将被唤醒，或者已经被唤醒。
         */
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

        /*
         * head后继一般能直接通过next找到，但只有prev是肯定有效的。
         * 所以遇到next为null，肯定需要从队尾的prev往前找。
         * 遇到next的状态为取消，也需要从队尾的prev往前找。
         */
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
        	// 如果遇到s == null，说明我们遇到一种中间状态，next指针还没有指好。如果遇到s.waitStatus > 0，说明head后继刚取消了。
        	//上面两种情况，都需要先置s为null，因为真正后继需要通过循环才能找到
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
            	// 注意循环条件t != null && t != node，它会从队尾一直往前找，直到t是null或t已经到达了node。
            	// 一般情况下，不会出现t != null，所以，这样循环肯定能找到node之后第一个不是取消状态的节点。
                if (t.waitStatus <= 0)
                	// 得到从tail往前找，距离node最近的，waitStatus<=0的节点
                    s = t;
        }
        if (s != null)
        	// 为s的线程，解除阻塞
            LockSupport.unpark(s.thread);
    }

    /**
     * 为共享模式释放动作——唤醒后继并确保传播。
     * (注意:在独占模式下，release只相当于调用head的unparkSuccessor，如果它需要signal。)
     * 
     * 这个函数的难点在于，很可能有多个线程同时在同时运行它。
     * 比如你创建了一个Semaphore(0)，让N个线程执行acquire()，自然这多个线程都会阻塞在acquire()这里，然后你让另一个线程执行release(N)。
     * 此时 释放共享锁的线程，肯定在执行doReleaseShared。
     * 
     * 由于 上面这个线程的unparkSuccessor，head后继的代表线程也会唤醒，进而执行doReleaseShared。
     * 重复第二步，获取共享锁的线程 又会唤醒 新head后继的代表线程。
     * 观察上面过程，有的线程 因为CAS操作失败，或head变化（主要是因为这个），会一直退不出循环。进而，可能会有多个线程都在运行该函数。
     * 
     * 由于共享锁在获取锁和释放锁时，都需要唤醒head后继，所以将其逻辑抽取成一个doReleaseShared的逻辑了。
     */
    private void doReleaseShared() {
        /*
         * 确保发布的传播，即使有其他正在进行的acquires/releases。
         * 如果head需要信号，则按照通常的方式尝试释放它的后继。
         * 但如果没有，则将status设置为PROPAGATE，以确保在释放时继续传播。
         * 此外，我们必须循环，以防止在执行此操作时添加新节点。
         * 另外，与unparkSuccessor的其他用途不同，我们需要知道CAS重置状态是否失败，如果失败，则重新检查。
         */
        for (;;) {
        	// 逻辑是一个死循环，每次循环中重新读取一次head，然后保存在局部变量h中，再配合if(h == head) break;，这样，循环检测到head没有变化时就会退出循环。
        	// 注意，head变化一定是因为：acquire thread被唤醒，之后它成功获取锁，然后setHead设置了新head。
        	// 而且注意，只有通过if(h == head) break;即head不变才能退出循环，不然会执行多次循环。
            Node h = head;
            if (h != null && h != tail) {
            	// if (h != null && h != tail)判断队列是否至少有两个node，如果队列从来没有初始化过（head为null），
            	// 或者head就是tail，那么中间逻辑直接不走，直接判断head是否变化了。
            	
            	// 如果队列中有两个或以上个node，那么检查局部变量h的状态：
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {
                	// 如果状态为SIGNAL，说明h的后继是需要被通知的。
                	// 通过对CAS操作结果取反，将compareAndSetWaitStatus(h, Node.SIGNAL, 0)和unparkSuccessor(h)绑定在了一起。
                	// 说明了只要head成功得从SIGNAL修改为0，那么head的后继的代表线程肯定会被唤醒了。
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;            // 循环检查案例
                    unparkSuccessor(h);// 如果把h的状态从signal改成0，解锁h的后继节点
                }
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                	// 如果状态为0，说明h的后继所代表的线程已经被唤醒或即将被唤醒，并且这个中间状态即将消失，
                	// 要么由于acquire thread获取锁失败再次设置head为SIGNAL并再次阻塞，要么由于acquire thread获取锁成功而将自己（head后继）
                	// 设置为新head并且只要head后继不是队尾，那么新head肯定为SIGNAL。
                	// 所以设置这种中间状态的head的status为PROPAGATE，让其status又变成负数，这样可能被 被唤醒线程
                	// （因为正常来讲，被唤醒线程的前驱，也就是head会被设置为0的，所以被唤醒线程发现head不为0，就会知道自己应该去唤醒自己的后继了） 检测到。
                	
                	// head状态为0的情况
                	// 如果等待队列中只有一个dummy node（它的状态为0），那么head也是tail，且head的状态为0。
                	
                	// 等待队列中当前只有一个dummy node（它的状态为0），acquire thread获取锁失败了（无论独占还是共享），
                	// 将当前线程包装成node放到队列中，此时队列中有两个node，但当前线程还没来得及执行一次shouldParkAfterFailedAcquire。
                	
                	// 此时队列中有多个node，有线程刚释放了锁，刚执行了unparkSuccessor里的if (ws < 0) compareAndSetWaitStatus(node, ws, 0);
                	// 把head的状态设置为了0，然后唤醒head后继线程，head后继线程获取锁成功，直到head后继线程将自己设置为AQS的新head的这段时间里，head的状态为0。
                	
                	// 具体地讲，如果是共享锁的话，一定是在调用unparkSuccessor之前就把head的状态变成0了，因为if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))。
                	
                	// 上面这种情况还可以继续延伸，在“唤醒head后继线程”后，head后继线程唤醒后第一次循环获取锁失败
                	//（你可能会疑问，上面的场景明明是刚有人释放了锁，为什么这里会失败，因为多线程环境下有可能被别的不公平获取方式插队了），
                	// 调用shouldParkAfterFailedAcquire又将head设置回SIGNAL了，然后第二次循环开始之前（假设head后继线程此时分出去时间片），
                	// 又有一个释放锁的线程在执行doReleaseShared里面的compareAndSetWaitStatus(h, Node.SIGNAL, 0)成功并且还unpark了处于唤醒状态的head后继线程，
                	// 然后第二次循环开始（假设head后继线程此时得到时间片），获取锁成功。
                	
                	// 注意，如果unpark一个已经唤醒的线程，它的副作用是下一次park这个线程，线程不会阻塞。下下次park线程，才会阻塞。
                	
                	// head状态为0的情况，属于一种中间状态。
                	// 这种中间状态将变化为，head状态为SIGNAL，不管acquire thread接下来是获取锁成功还是失败。不过获取锁成功这种情况，需要考虑head后继
                	//（也就是包装acquire thread的那个node）不是队尾，如果是队尾，那么新head的状态也是为0的了。
                	
                    continue;                // 如果把h的状态从0改成PROPAGATE失败，继续循环
            }
            // 如果状态为PROPAGATE，直接判断head是否变化。
            // 两个continue保证了进入那两个分支后，只有当CAS操作成功后，才可能去执行if(h == head) break;，才可能退出循环。
            
            // if(h == head) break;保证了，只要在某个循环的过程中有线程刚获取了锁且设置了新head，就会再次循环。
            // 目的当然是为了再次执行unparkSuccessor(h)，即唤醒队列中第一个等待的线程。
            if (h == head)                   // 如果head变了，继续循环
                break;
        }
    }

    /**
     * 设置队列头，并检查后来者是否可以在共享模式下等待，
     * 如果propagate> 0或propagate状态被设置，这样传播。
     * 
     * setHead函数只是将刚成为将成为head的节点变成一个dummy node。
     * 而setHeadAndPropagate里也会调用setHead函数。但是它在一定条件下还可能会调用doReleaseShared，
     * 看来这就是单词Propagate的由来了，也就是我们一直说的“如果一个线程刚获取了共享锁，那么在其之后等待的线程也很有可能能够获取到锁”。
     *
     * @param node the node
     * @param propagate the return value from a tryAcquireShared
     */
    private void setHeadAndPropagate(Node node, int propagate) {
        Node h = head; // 记录旧头以便在下面的检查
        setHead(node);
        /*
         * 尝试唤醒下一个队列节点，如果:
         *   传播是由调用者指示的，或者是由上一个操作记录(作为h.waitStatus，在setHead之前或之后)，
         *   (注意:这个操作使用waitStatus的符号检查，因为传播状态可能会转换为SIGNAL)
         *     
         *     下一个节点在共享模式下等待，或者我们不知道，因为它看起来是空的
         *
         * 这两种检查的保守性可能会导致不必要的唤醒，
         * 但只有在存在多个竞争获取/释放时才会如此，所以大多数情况下现在或很快就需要信号。
         */
        if (propagate > 0 || h == null || h.waitStatus < 0 ||
            (h = head) == null || h.waitStatus < 0) {
            Node s = node.next;
            if (s == null || s.isShared())
                doReleaseShared();
        }
    }

    // 不同版本acquire的工具方法

    /**
     * 取消正在进行的acquire尝试。
     * 
     * 回忆起node有一种CANCELLED状态，看来就是为cancelAcquire(node)准备的了。
     * 
     * 如果闹钟设置成功，且闹钟都在node不是一个dummy node，那么将pred与node后继相连，让node后继继续安心睡觉。
     * 如果发现node后继已经是排队的第一个了、发现闹钟没有设置成功、发现闹钟设置成功但闹钟所在节点变空节点，都需要唤醒node后继。
     *
     * @param node the node
     */
    private void cancelAcquire(Node node) {
        // 如果node不存在则忽略
        if (node == null)
            return;

        // 先设置node的thread为null
        node.thread = null;

        // 循环用来跳过无效前驱
        Node pred = node.prev;
        while (pred.waitStatus > 0)
            node.prev = pred = pred.prev;

        // 执行完循环，pred会指向node的有效前驱。
        // 当然，如果node的前驱就是有效的。那么就不需要跳过了。

        // pred的后继无论如何都需要取消，因为即使前面循环没有执行，
        // 现在pred的后继（肯定是参数node）也是一个马上取消掉的node。
        // 之后有些CAS操作会尝试修改pred的后继，如果CAS失败，那么说明有别的线程在做
        // 取消动作或通知动作，所以当前线程也不需要更多的动作了。
        Node predNext = pred.next;

        // 这里直接使用赋值操作，而不是CAS操作。
        // 如果别的线程在执行这步之后，别的线程将会跳过这个node。
        // 如果别的线程在执行这步之前，别的线程还是会将这个node当作有效节点。
        node.waitStatus = Node.CANCELLED;
        
        // 注意：调用cancelAcquire后，会从doAcquireXXX方法返回，整个方法执行完成
        // node节点自己的状态为cancelled
        // 方法执行完后，就不会唤醒在node之后的节点了，所以要让pred.next=node.next，并且pred状态为signal，或者直接唤醒node.next

        // 如果node是队尾，那简单。直接设置pred为队尾，然后设置pred的后继为null
        // 如果node是队尾，那说明node后面没有节点，也就不存在节点需要去唤醒了。
        if (node == tail && compareAndSetTail(node, pred)) {
            compareAndSetNext(pred, predNext, null);
        } else {
        	// 如果node不是队尾，node则有后继。
            // 分析node不是队尾的情况，既然不是队尾，说明node后面有节点。如下图所示。
        	// 这里面又有分支，先直接看进入分支要做什么，再来分析进入分支的条件：
        	// 在if分支里，去做compareAndSetNext(pred, predNext, next)，即修复pred的后继，完善双向链表的指针。但这样做有一个前提，就是需要pred的状态已经是SIGNAL的了。
        	// 在else分支里，去做unparkSuccessor(node)，去唤醒node后继。
        	
        	// pred  predNext  otherCancelled  node  nodeNext
        	// 从上图可以看到，实际意义上，pred的后继已经变成了node后继了。

        	// pred != head不成立，那么说明pred就是head，执行else分支。node的后继运气爆棚，因为node自己取消掉了，
        	// node的后继便成为了等待队列中第一个线程（即成为了head后继），自然需要去唤醒它了（unparkSuccessor(node)）。
        	
        	// pred != head成立，但(ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))不成立，执行else分支。
        	// 第一个条件成立，说明pred并不是head。
        	// 第二个条件不成立，里面是||，说明是两个子条件都不成立。有下面情况：
        	
        	// 如果pred的状态是CANCELLED。这似乎有点矛盾，因为之前的for循环已经判断过pred的状态是 <= 0的了，
        	// 但你要知道多线程环境下，什么都可能发生。很可能从for循环执行到这里的时候，pred又被取消掉了。
        	// 考虑到pred如果是head后继的话，那么node后继就一下子成为了队列中第一个线程了，所以还是有必要执行unparkSuccessor(node)。
        	// 如果pred的状态是 <= 0但还不是SIGNAL，但CAS设置pred的状态为SIGNAL却失败了。
        	// SIGNAL是作为后继节点被唤醒的标志而存在的，现在居然没有设置成功，所以很有必要执行unparkSuccessor(node)。
        	
        	// pred != head成立，(ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))也成立，
        	// 但pred.thread != null不成立，执行else分支。
        	// 第一个条件成立，说明pred并不是head。
        	// 第二个条件成立，里面是||，说明是两个子条件要么前真，要么前假后真。
        	
        	// 如果是前真，那么说明pred的状态已经是SIGNAL。
        	// 如果是前假后真，那么说明pred的状态是0或PROPAGATE，且接下来的CAS操作也成功了，即成功设置为SIGNAL。
        	// 第三个条件不成立，说明pred变成了一个dummy node了。要么pred是变成head了，要么pred突然被取消了（执行了node.thread = null）。
        	// 这两种情况，前者必须执行unparkSuccessor(node)，后者只是有必要执行。
        	
        	// pred != head成立，(ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))也成立，
        	// 且pred.thread != null也成立，只有这里才执行if分支。说明闹钟设置成功，并且设置的node也不是个空节点，
        	// 那么只需要将pred与node后继相连即可（compareAndSetNext(pred, predNext, next)）。
            int ws;
            if (pred != head &&
                ((ws = pred.waitStatus) == Node.SIGNAL ||
                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                pred.thread != null) {
                Node next = node.next;
                if (next != null && next.waitStatus <= 0)
                	// pred的next设置为next
                    compareAndSetNext(pred, predNext, next);
            } else {
                unparkSuccessor(node);
            }

            node.next = node; // help GC
        }
    }

    /**
     * 检查并更新未能acquire的节点的状态。如果线程应该阻塞，则返回true。
     * 这是所有acquire循环中的主要信号控制。要求pred == node.prev。
     * 
     * shouldPark：指的是 该函数的返回值影响是否可以执行parkAndCheckInterrupt函数。
     * 因为shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()这么写，只有当该函数返回true时，才会去执行parkAndCheckInterrupt。
     * 注意，parkAndCheckInterrupt函数执行后，当前线程就会被挂起了，也就是我们所说的阻塞。
     * 
     * AfterFailedAcquire：指的是 获取锁失败了才会执行该函数。其实具体指两种情况：
     * 1. p == head为false，即当前线程的node的前驱不是head 
     * 2. 虽然 p == head为true，但parkAndCheckInterrupt返回false了，即当前线程虽然已经排到等待队列的最前面，但获取锁还是失败了。
     * 
     * static final int CANCELLED =  1;
     * static final int SIGNAL    = -1;
     * static final int CONDITION = -2;
     * static final int PROPAGATE = -3;
     * 
     * node一共有四种状态，但在独占锁的获取和释放过程中，我们只可能将node的状态变成CANCELLED或SIGNAL，而shouldParkAfterFailedAcquire函数就会把一个node的状态变成SIGNAL。
     * 注意，一个node新建的时候，它的waitStatus是默认初始化为0的。
     * CANCELLED，一个node的状态是CANCELLED，说明这个node的代表线程已经取消等待了。
     * 
     * SIGNAL，一个node的状态是SIGNAL，说明这个node的后继node的代表线程已经阻塞或马上阻塞（shouldParkAfterFailedAcquire设置前驱为SIGNAL后，
     * 下一次的acquireQueued循环可能就会阻塞了，所以说“已经阻塞或马上阻塞”），并且当前node成为head并释放锁时，会根据SIGNAL来唤醒后继node。
     * 即SIGNAL是唤醒后继节点的标志。
     * 有趣的是，CANCELLED状态与当前node关联，SIGNAL状态与后继node关联。
     * 本函数，简单的讲就是，跳过无效前驱，把node的有效前驱（有效是指node不是CANCELLED的）找到，并且将有效前驱的状态设置为SIGNAL，之后便返回true代表马上可以阻塞了。
     * 
     * 由于shouldParkAfterFailedAcquire函数在acquireQueued的调用中处于一个死循环中，
     * 且因为shouldParkAfterFailedAcquire函数若返回false，且考虑当前线程一直不能获取到锁的情况，那么此函数必将至少执行两次才能阻塞自己。
     * shouldParkAfterFailedAcquire只有在检测到前驱的状态为SIGNAL才能返回true，只有true才会执行到parkAndCheckInterrupt。
     * shouldParkAfterFailedAcquire返回false后，进入下一次循环，当前线程又会再次尝试获取锁（p == head && tryAcquire(arg)）。
     * 
     * 或者说，每次执行shouldParkAfterFailedAcquire，都说明当前循环 尝试过获取锁了，但失败了。
     * 如果刚开始前驱的状态为0，那么需要第一次执行compareAndSetWaitStatus(pred, ws, Node.SIGNAL)返回false并进入下一次循环，
     * 第二次才能进入if (ws == Node.SIGNAL)分支，所以说 至少执行两次。
     * 死循环保证了node自己被阻塞前，一定能设置前驱为SIGNAL成功的。（考虑当前线程一直不能获取到锁）
     *
     * @param pred node's predecessor holding status
     * @param node the node
     * @return {@code true} if thread should block
     */
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            /*
             * 前驱节点已经设置了SIGNAL，闹钟已经设好，现在我可以安心睡觉（阻塞）了。
             * 如果前驱变成了head，并且head的代表线程exclusiveOwnerThread释放了锁，
             * 就会来根据这个SIGNAL来唤醒自己
             */
            return true;
        if (ws > 0) {
            /*
             * 发现传入的前驱的状态大于0，即CANCELLED。说明前驱节点已经因为超时或响应了中断，而取消了自己。
             * 所以需要跨越掉这些CANCELLED节点，直到找到一个<=0的节点，即一个有效节点，再把node和这个有效节点的前驱后继连接好。
             */
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * 进入这个分支，ws只能是0或PROPAGATE。
             * CAS设置ws为SIGNAL
             */
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

    /**
     * 中断当前线程的方便方法。
     */
    static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

    /**
     * park，然后检查是否中断的方便方法。
     * 
     * 既然shouldParkAfterFailedAcquire已经返回了true，那么我现在可以执行parkAndCheckInterrupt了。
     * 
     * 调用完LockSupport.park(this)，当前线程就阻塞在这里，直到有别的线程unpark了当前线程，或者中断了当前线程。
     * 而返回的Thread.interrupted()代表当前线程在阻塞的过程中，有没有被别的线程中断过，如果有，则返回true。
     * 注意，Thread.interrupted()会消耗掉中断的状态，即第一次执行能返回true，但紧接着第二次执行就只会返回false了。
     * 
     * 如果是别的线程unpark了当前线程，那么调用Thread.interrupted()返回false。
     * 如果是别的线程中断了当前线程，那么调用Thread.interrupted()返回true。
     *
     * @return {@code true} if interrupted
     */
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

    /*
     * 各种各样的acquire方式，在排他性/共享和控制模式中有所不同。
     * 它们基本上是一样的，但却有恼人的不同。
     * 由于异常机制(包括确保在tryAcquire抛出异常时取消)和其他控制的交互作用，
     * 只有少量的分解是可能的，至少不会对性能造成太大的损害。
     */

    /**
     * 以独占不可中断模式获取已经在队列中的线程。用于条件等待方法和acquire方法。
     * 
     * acquireQueued函数是整个独占锁获取的精华部分，它解释了独占锁获取的整个过程。
     * 执行到这个函数，说明：
     * 
     * 当前线程已经执行完了addWaiter方法。
     * 传入的node的thread成员就是当前线程。
     * 传入的node已经成功入队。（addWaiter的作用）
     * 
     * 简单的说，acquireQueued是利用自旋+tryAcquire“不断”地尝试获取锁，当然实际上如果真的是在死循环来不断调tryAcquire，肯定电脑都卡死了。实际流程是：
     * 每次循环都会判断是否可以尝试获取锁（p == head），如果可以，那么尝试（tryAcquire(arg)）。
     * 如果尝试获取锁成功，那么函数的使命就达到了，执行完相应收尾工作，然后返回。
     * 如果 不可以尝试 或者 尝试获取锁却失败了，那么阻塞当前线程（parkAndCheckInterrupt）。
     * 如果当前线程被唤醒了，又会重新走这个流程。被唤醒时，是从parkAndCheckInterrupt处唤醒，然后从这里继续往下执行。
     * 
     * 执行acquireQueued的线程是谁？
     * 一定是node参数的thread成员，虽然执行过程中，可能会经历不断 阻塞和被唤醒 的过程。
     *
     * @param node the node
     * @param arg the acquire argument
     * @return {@code true} if interrupted while waiting
     */
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                // 为什么tryAcquire(arg)的前提是p == head？
                // 因为从enq的逻辑可知，head只会是一个dummy node，实际意义的node只会在head的后面。
                // 而node的前驱是head（final Node p = node.predecessor()），则代表node已经是队列中的第一个实际node了，排在最前面的node自然可以尝试去获取锁了。
                
                // 回想整个调用过程，是最开始在acquire里调用tryAcquire就已经失败了，然而此时第一次循环时，又可能马上去调tryAcquire
                //（说可能，是因为需要p == head成立），这会不会是一次肯定失败的tryAcquire？
                // 考虑这种场景，线程1获取了锁正在使用还没释放，此时队列为空，线程2此时也来获取锁，自然最开始在acquire里调用tryAcquire会失败，
                // 假设线程2刚开始执行acquireQueued，此时线程1释放了锁，此时线程2肯定排在head后面，那么线程2马上tryAcquire，然后就可以获取成功。
                
                // 为什么刚执行完addWaiter方法时，才把代表当前线程的node放到队尾，怎么之后一判断就会发现自己处于head的后继了？
                // 这个问题不考虑上面的特殊场景，而考虑addWaiter时，队列中有许多node。
                // 其实这很合理，这说明从head到当前方法栈中的node之间的那些node，它们自己也会在执行acquireQueued，它们依次执行成功
                //（指p == head && tryAcquire(arg)成功），每次执行成功相当于把head成员从队列上后移一个node，当它们都执行完毕，当前方法栈中的node自然也就是head的后继了。
                // 注意，“之间的那些node”的最后一个node执行acquireQueued成功后（代表 最后一个node的代表线程获得锁成功，它自己成为了head），
                // 当前方法还在阻塞之中，只有当这“最后一个node”释放独占锁时，才会执行unparkSuccessor(head)，当前线程才会被唤醒。关于释放独占锁，以后再具体讲。
                if (p == head && tryAcquire(arg)) {
                	// 从逻辑中可见，如果当前线程获取锁成功，代表当前线程的node会新设置自己为head，然后将其弄成dummy node，
                	// 即把node的thread成员清空，但这个被清空的thread成员已经在tryAcquire里将这个thread设置为了exclusiveOwnerThread。
                	// 可以这么理解，head之所以它的thread成员为null，是因为它的thread成员被放在了exclusiveOwnerThread成员里。
                	// 使用setHead而非compareAndSetHead，因为此时不需要CAS操作，执行到这里说明当前线程已经获得了独占锁（tryAcquire成功），所以别的线程是不可能同时执行这部分代码的。
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                	// 如果线程不应该阻塞，进入下一个循环
                	// 如果线程要阻塞，进行阻塞，醒来后，检查interrupt，然后赋值给interrupted，最后获取锁的时候返回interrupted
                	
                	// head后继当初是阻塞在了parkAndCheckInterrupt()这里，根据它的返回值，我们将设置interrupted变量，以在返回用户代码之前，补上中断状态。
                	// 被唤醒的线程将开始下一次循环，最重要的，会再一次执行p == head && tryAcquire(arg)，考虑本文的流程且没有别的线程竞争的话，此处的tryAcquire必定能成功。
                    interrupted = true; // 这里设置后，会被永久保留
            }
        } finally {
        	// finally块是否会执行cancelAcquire(node)？
        	// 虽然号称此函数是不响应中断的函数，但不响应中断只是对于AQS的使用者来说，如果一个线程阻塞在parkAndCheckInterrupt这里，
        	// 别的线程来中断它，它是会马上唤醒的，然后继续这个循环。不过想要退出这个函数，只有通过return interrupted，而前一句就是failed = false，
        	// 所以finally块里，是永远不会去执行cancelAcquire(node)的。
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * 以独占可中断模式获取。
     * 
     * 而doAcquireInterruptibly方法 的相对应的方法为acquireQueued方法。观察两个方法的差别很少：
     * 
     * doAcquireInterruptibly没有返回值，而acquireQueued方法有返回值，代表当前线程是否被中断过。
     * acquireQueued方法需要有返回值，因为函数调用返回上层后，需要根据返回值来判断是否需要重新设置中断状态，在返回用户代码之前。
     * doAcquireInterruptibly不需要返回值，因为该函数中如果检测到了中断状态，就直接抛出异常就好了。
     * 
     * @param arg the acquire argument
     */
    private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
    	// 队尾增加一个独占的节点
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                	// 如果醒来后，发现被中断了，报出异常
                    throw new InterruptedException();
            }
        } finally {
        	// doAcquireInterruptibly方法的finally块是可能会执行到cancelAcquire(node)的，而acquireQueued方法不可能去执行cancelAcquire(node)的。
        	// 在doAcquireInterruptibly方法中，如果线程阻塞在parkAndCheckInterrupt这里后，别的线程来中断阻塞线程，阻塞线程会被唤醒，然后抛出异常。
        	// 本来抛出异常该函数就马上结束掉的，但由于有finally块，所以在结束掉之前会去执行finally块，并且由于failed为true，则会执行cancelAcquire(node)。
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * 在独占时间模式下获取。
     * 
     * 将doAcquireNanos方法 与不响应中断的acquireQueued方法、响应中断的doAcquireInterruptibly方法进行对比，发现差别很少。
     * 每次循环都会检查时间是否到达deadline。
     * 当剩余时间小于spinForTimeoutThreshold时，则不能调用LockSupport.parkNanos，因为时间太短，反而无法精确控制阻塞时间，所以不如在剩余的时间里一直循环。
     * 
     * LockSupport.parkNanos除了会因为别人的park而唤醒，也会因为别人的中断而唤醒，当然最重要的，时间到了，它自己会唤醒。
     * 不管哪种情况，被唤醒后，都会检查中断状态。每个循环都会检查一次。
     *
     * @param arg the acquire argument
     * @param nanosTimeout max wait time
     * @return {@code true} if acquired
     */
    private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)//如果时间小于0，直接返回失败
            return false;
        //算出“死期”，当死期到了就直接返回失败了
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
                nanosTimeout = deadline - System.nanoTime();
                //小于0，说明死期到了
                if (nanosTimeout <= 0L)
                    return false;
                //剩余寿命得大于1ms
                if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                // 如果被中断了，报出异常
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * 在共享不可中断模式下acquire
     * 
     * 共享锁的doAcquireShared有两处不同：
     * 
     * 创建的节点不同。共享锁使用addWaiter(Node.SHARED)，所以会创建出想要获取共享锁的节点。
     * 而独占锁使用addWaiter(Node.EXCLUSIVE)。
     * 
     * 获取锁成功后的善后操作不同。共享锁使用setHeadAndPropagate(node, r)，因为刚获取共享锁成功后，
     * 后面的线程也有可能成功获取，所以需要在一定条件唤醒head后继。而独占锁使用setHead(node)。
     * 
     * @param arg the acquire argument
     */
    private void doAcquireShared(int arg) {
        final Node node = addWaiter(Node.SHARED);//这件事放到里面来了
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                //前驱是head时，才尝试获得共享锁
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                    	// 如果试图acquire共享成功，设置node为head，并且进行宣传
                        setHeadAndPropagate(node, r);//独占锁这里调用的是setHead
                        p.next = null; 
                        if (interrupted)
                            selfInterrupt();//这件事也放到里面来了
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * 在共享可中断模式下acquire
     * @param arg the acquire argument
     */
    private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    /**
     * 在共享时间模式下acquire
     *
     * @param arg the acquire argument
     * @param nanosTimeout max wait time
     * @return {@code true} if acquired
     */
    private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return true;
                    }
                }
                nanosTimeout = deadline - System.nanoTime();
                if (nanosTimeout <= 0L)
                    return false;
                if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    // 主要的导出的方法

    /**
     * 试图以独占模式获取。
     * 这个方法应该查询对象的状态是否允许以独占模式获取它，如果允许则获取它。
     *
     * <p>这个方法总是由执行acquire的线程调用。
     * 如果这个方法报告失败，如果这个线程还没有进入队列，
     * acquire方法可能会让它进入队列，直到它收到来自其他线程的释放信号。
     * 这可以用来实现Lock.tryLock()方法。
     *
     * <p>缺省实现抛出UnsupportedOperationException。
     *
     * @param arg the acquire argument. This value is always the one
     *        passed to an acquire method, or is the value saved on entry
     *        to a condition wait.  The value is otherwise uninterpreted
     *        and can represent anything you like.
     * @return {@code true} if successful. Upon success, this object has
     *         been acquired.
     * @throws IllegalMonitorStateException if acquiring would place this
     *         synchronizer in an illegal state. This exception must be
     *         thrown in a consistent fashion for synchronization to work
     *         correctly.
     * @throws UnsupportedOperationException if exclusive mode is not supported
     */
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 试图设置状态以反映独占模式下的释放。
     *
     * <p>这个方法总是由执行release的线程调用。
     *
     * <p>默认实现抛出UnsupportedOperationException。
     *
     * @param arg the release argument. This value is always the one
     *        passed to a release method, or the current state value upon
     *        entry to a condition wait.  The value is otherwise
     *        uninterpreted and can represent anything you like.
     * @return {@code true} if this object is now in a fully released
     *         state, so that any waiting threads may attempt to acquire;
     *         and {@code false} otherwise.
     * @throws IllegalMonitorStateException if releasing would place this
     *         synchronizer in an illegal state. This exception must be
     *         thrown in a consistent fashion for synchronization to work
     *         correctly.
     * @throws UnsupportedOperationException if exclusive mode is not supported
     */
    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 试图以共享模式获取。这个方法应该查询对象的状态
     * 是否允许在共享模式中获取它，如果允许，就获取它。
     *
     * <p>这个方法总是由执行acquire的线程调用。
     * 如果这个方法报告失败，如果这个线程还没有进入队列，
     * acquire方法可能会让它进入队列，直到它收到来自其他线程的释放信号。
     *
     * <p>默认实现抛出UnsupportedOperationException。
     *
     * @param arg the acquire argument. This value is always the one
     *        passed to an acquire method, or is the value saved on entry
     *        to a condition wait.  The value is otherwise uninterpreted
     *        and can represent anything you like.
     * @return a negative value on failure; zero if acquisition in shared
     *         mode succeeded but no subsequent shared-mode acquire can
     *         succeed; and a positive value if acquisition in shared
     *         mode succeeded and subsequent shared-mode acquires might
     *         also succeed, in which case a subsequent waiting thread
     *         must check availability. (Support for three different
     *         return values enables this method to be used in contexts
     *         where acquires only sometimes act exclusively.)  Upon
     *         success, this object has been acquired.
     * @throws IllegalMonitorStateException if acquiring would place this
     *         synchronizer in an illegal state. This exception must be
     *         thrown in a consistent fashion for synchronization to work
     *         correctly.
     * @throws UnsupportedOperationException if shared mode is not supported
     */
    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 尝试设置状态以反映共享模式下的释放。
     *
     * <p>这个方法总是由执行release的线程调用。
     *
     * <p>默认实现抛出UnsupportedOperationException。
     *
     * @param arg the release argument. This value is always the one
     *        passed to a release method, or the current state value upon
     *        entry to a condition wait.  The value is otherwise
     *        uninterpreted and can represent anything you like.
     * @return {@code true} if this release of shared mode may permit a
     *         waiting acquire (shared or exclusive) to succeed; and
     *         {@code false} otherwise
     * @throws IllegalMonitorStateException if releasing would place this
     *         synchronizer in an illegal state. This exception must be
     *         thrown in a consistent fashion for synchronization to work
     *         correctly.
     * @throws UnsupportedOperationException if shared mode is not supported
     */
    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 如果同步是针对当前(调用)线程独占持有的，则返回true。
     * 每次调用非等待的ConditionObject方法时都会调用这个方法。(等待方法调用release。)
     *
     * <p>默认实现抛出UnsupportedOperationException。
     * 此方法仅在条件对象方法内部调用，因此如果不使用条件，则不需要定义。
     *
     * @return {@code true} if synchronization is held exclusively;
     *         {@code false} otherwise
     * @throws UnsupportedOperationException if conditions are not supported
     */
    protected boolean isHeldExclusively() {
        throw new UnsupportedOperationException();
    }

    /**
     * 以独占模式获取，忽略中断。
     * 通过至少调用一次tryAcquire来实现，成功时返回。
     * 否则，线程将进入队列，可能会反复阻塞和解除阻塞，调用tryAcquire直到成功。
     * 这个方法可以用来实现Lock.lock方法。
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquire} but is otherwise uninterpreted and
     *        can represent anything you like.
     */
    public final void acquire(int arg) {
    	// 先试图获取锁
    	// 如果失败，先创建一个独占的节点，加入队列尾部
    	// 然后在队列中，阻塞，然后被唤醒，然后如果前节点为head，则重新试图获得锁，如果失败，可能再次阻塞。
    	// 如果在队列中被中断过，则进行中断
    	
    	// tryAcquire用来获取独占锁一次，try的意思就是只试一次，要么成功，要么失败。
    	// tryAcquire返回true时，后面的三个函数都不会执行了。
    	// tryAcquire返回false时，必将调用addWaiter和acquireQueued。
    	
    	// addWaiter是AQS的实现，因为开始获取锁失败了（tryAcquire返回false），所以需要把当前线程包装成node放到等待队列中，返回代表当前线程的node。
    	// acquireQueued是AQS的实现，简单的理解就是：用一个死循环不断得去执行tryAcquire，直到获取锁。当然：
    	// 程序不会真的在死循环，一般情况下，会不断经历 阻塞和被唤醒 两种状态。
    	// 当参数node的前驱是head时，才会去tryAcquire尝试获得锁。
    	
    	// selfInterrupt用来复原中断状态，虽然这个版本的函数不用响应中断。当acquireQueued返回真时，代表这期间函数曾经检测到过中断状态，
    	// 并且将中断状态消耗掉了（Thread.interrupted()），所以需要在退出acquire之前，将中断状态重新设置上。
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    /**
     * 以独占模式获取，如果中断将中止。
     * 首先检查中断状态，然后至少调用一次tryAcquire，成功则返回。
     * 否则，线程将进入队列，可能会重复地阻塞和解除阻塞，调用tryAcquire直到成功或线程被中断。
     * 这个方法可以用来实现Lock.lockInterruptibly方法。
     * 
     * 从下面函数中，可以看到函数都会抛出InterruptedException异常，这是我们能看到的第一处不同。
     * 
     * acquireInterruptibly这个方法与 不响应中断的acquire方法 对应。
     * 同样的，进入这个方法后，会第一次进行tryAcquire尝试。
     * 但不同的，此acquireInterruptibly函数中，会去检测Thread.interrupted()，并抛出异常。
     * 但注意，对于acquireInterruptibly这个方法而言，既可以是公平的，也可以是不公平的，
     * 这完全取决于tryAcquire的实现（即取决于ReentrantLock当初是怎么构造的）。
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquire} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @throws InterruptedException if the current thread is interrupted
     */
    public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (!tryAcquire(arg))
            doAcquireInterruptibly(arg);
    }

    /**
     * 尝试以独占模式获取，如果被中断，则中止，如果给定超时，则失败。
     * 首先检查中断状态，然后至少调用一次tryAcquire，成功时返回。
     * 否则，线程将进入队列，可能会反复阻塞和解除阻塞，调用tryAcquire直到成功或线程被中断或超时。
     * 这个方法可以用来实现Lock.tryLock(long, TimeUnit)。
     * 
     * tryAcquireNanos这个方法与 不响应中断的acquire方法 对应。
     * 同样的，进入这个方法后，会第一次进行tryAcquire尝试。
     * 但不同的，此tryAcquireNanos函数中，会先去检测Thread.interrupted()，并抛出异常。
     * 
     * 但注意，对于tryAcquireNanos这个方法而言，既可以是公平的，也可以是不公平的，
     * 这完全取决于tryAcquire的实现（即取决于ReentrantLock当初是怎么构造的）。
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquire} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @param nanosTimeout the maximum number of nanoseconds to wait
     * @return {@code true} if acquired; {@code false} if timed out
     * @throws InterruptedException if the current thread is interrupted
     */
    public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquire(arg) ||
            doAcquireNanos(arg, nanosTimeout);
    }

    /**
     * 在独占模式下释放。通过解除一个或多个线程的阻塞来实现，如果tryRelease返回true。
     * 此方法可用于实现Lock.unlock方法。
     *
     * @param arg the release argument.  This value is conveyed to
     *        {@link #tryRelease} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @return the value returned from {@link #tryRelease}
     */
    public final boolean release(int arg) {
        if (tryRelease(arg)) { // 尝试释放锁tryRelease，这是子类的实现。
            Node h = head;
            // h != null标准地防止空指针，不过这种情况肯定也有，比如从头到尾都只有一个线程在使用锁，那么队列也不会初始化，head肯定为null。
            // 使用h.waitStatus != 0作为唤醒head后继的判断标准，当队列只有一个dummy node时，它的状态为0，也就不会执行unparkSuccessor(h)了。
            // 当head的状态为SIGNAL时，说明head后继已经设置了闹钟，会执行unparkSuccessor(h)。
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

    /**
     * 以共享模式获取，忽略中断。
     * 首先调用至少一次tryAcquireShared，成功后返回。
     * 否则，线程将进入队列，可能会反复阻塞和解除阻塞，调用tryAcquireShared直到成功。
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquireShared} but is otherwise uninterpreted
     *        and can represent anything you like.
     */
    public final void acquireShared(int arg) {
    	// 咋一看感觉差别有点大，其实我们被迷惑了，后面我们会发现，
    	// 之所以acquireShared里没有显式调用addWaiter和selfInterrupt，是因为这两件事都被放到了doAcquireShared(arg)的逻辑里面了。
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }

    /**
     * 以共享模式获取，如果中断将中止。
     * 首先检查中断状态，然后至少调用一次tryAcquireShared，成功时返回。
     * 否则，线程将进入队列，可能会反复阻塞和解除阻塞，调用tryAcquireShared直到成功或线程被中断。
     * 
     * @param arg the acquire argument.
     * This value is conveyed to {@link #tryAcquireShared} but is
     * otherwise uninterpreted and can represent anything
     * you like.
     * @throws InterruptedException if the current thread is interrupted
     */
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }

    /**
     * 尝试以共享模式获取，如果被中断，将中止，如果给定超时，将失败。
     * 首先检查中断状态，然后至少调用一次tryAcquireShared，成功时返回。
     * 否则，线程将进入队列，可能会反复阻塞和解除阻塞，调用tryAcquireShared直到成功或线程被中断或超时。
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquireShared} but is otherwise uninterpreted
     *        and can represent anything you like.
     * @param nanosTimeout the maximum number of nanoseconds to wait
     * @return {@code true} if acquired; {@code false} if timed out
     * @throws InterruptedException if the current thread is interrupted
     */
    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquireShared(arg) >= 0 ||
            doAcquireSharedNanos(arg, nanosTimeout);
    }

    /**
     * 在共享模式下释放。
     * 通过解除一个或多个线程的阻塞来实现，如果tryReleaseShared返回true。
     * 
     * 独占锁的逻辑比较简单，只是在head状态不为0时，就唤醒head后继。
     * 
     * 而共享锁的逻辑则直接调用了tryReleaseShared，但在获取共享锁成功时，也可能会调用到doReleaseShared。
     * 也就是说，获取共享锁的线程（分为：已经获取到的线程 即执行setHeadAndPropagate中、
     * 等待获取中的线程 即阻塞在shouldParkAfterFailedAcquire里）
     * 和释放共享锁的线程 可能在同时执行这个doReleaseShared。
     *
     * @param arg the release argument.  This value is conveyed to
     *        {@link #tryReleaseShared} but is otherwise uninterpreted
     *        and can represent anything you like.
     * @return the value returned from {@link #tryReleaseShared}
     */
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

    // 队列检验方法

    /**
     * 查询是否有等待获取的线程。
     * 请注意，由于中断和超时导致的取消可能在任何时候发生，返回true并不保证任何其他线程会acquire。
     *
     * <p>在这个实现中，这个操作在常量时间返回。
     *
     * @return {@code true} if there may be other threads waiting to acquire
     */
    public final boolean hasQueuedThreads() {
        return head != tail;
    }

    /**
     * 查询是否有线程竞争获取这个同步器;既是是否有一个已经阻塞的acquire方法。
     *
     * <p>在这个实现中，这个操作在常量时间返回。
     *
     * @return {@code true} if there has ever been contention
     */
    public final boolean hasContended() {
        return head != null;
    }

    /**
     * 返回队列中第一个(等待时间最长的)线程，如果当前没有线程排队，则返回null。
     *
     * <p>在这个实现中，这个操作通常在常量时间内返回，
     * 但如果其他线程并发地修改队列，则可能在争用时进行迭代。
     *
     * @return the first (longest-waiting) thread in the queue, or
     *         {@code null} if no threads are currently queued
     */
    public final Thread getFirstQueuedThread() {
        // handle only fast path, else relay
        return (head == tail) ? null : fullGetFirstQueuedThread();
    }

    /**
     * 当fastpath失败时调用的getFirstQueuedThread版本
     */
    private Thread fullGetFirstQueuedThread() {
        /*
         * 第一个节点通常是head.next。
         * 尝试获取它的线程字段，确保一致的读取:
         * 如果线程字段为空或s.prev不再是head，那么一些其他线程(s)在我们的两次读取之间，并发执行setHead。
         * 在进行遍历之前，我们尝试了两次。
         */
        Node h, s;
        Thread st;
        if (((h = head) != null && (s = h.next) != null &&
             s.prev == head && (st = s.thread) != null) ||
            ((h = head) != null && (s = h.next) != null &&
             s.prev == head && (st = s.thread) != null))
            return st;

        /*
         * Head的next字段可能还没有设置，或者可能在setHead之后没有设置。
         * 所以我们必须检查tail是否是第一个结点。
         * 如果没有，我们继续，安全地从尾部回到头部找到第一个，保证终止。
         */

        Node t = tail;
        Thread firstThread = null;
        while (t != null && t != head) {
            Thread tt = t.thread;
            if (tt != null)
                firstThread = tt;
            t = t.prev;
        }
        return firstThread;
    }

    /**
     * 如果给定的线程当前正在排队，则返回true。
     *
     * <p>这个实现遍历队列以确定给定线程的存在。
     *
     * @param thread the thread
     * @return {@code true} if the given thread is on the queue
     * @throws NullPointerException if the thread is null
     */
    public final boolean isQueued(Thread thread) {
        if (thread == null)
            throw new NullPointerException();
        for (Node p = tail; p != null; p = p.prev)
            if (p.thread == thread)
                return true;
        return false;
    }

    /**
     * 如果第一个排队的线程(如果存在的话)正在排他模式等待，则返回true。
     * 如果这个方法返回true，并且当前线程正在尝试获取共享模式
     * (也就是说，这个方法是从tryAcquireShared调用的)，那么它保证当前线程不是第一个排队的线程。
     * 仅作为一个启发式ReentrantReadWriteLock的NonfairSync的readerShouldBlock方法调用。
     */
    final boolean apparentlyFirstQueuedIsExclusive() {
        Node h, s;
        return (h = head) != null &&
            (s = h.next)  != null &&
            !s.isShared()         &&
            s.thread != null;
    }

    /**
     *  查询是否有线程等待获取的时间长于当前线程。
     *
     * <p>调用此方法等价于(但可能个更有效):
     *  <pre> {@code
     * getFirstQueuedThread() != Thread.currentThread() &&
     * hasQueuedThreads()}</pre>
     *
     * <p>注意，由于中断和超时导致的取消可能在任何时候发生，返回true并不保证其他线程会在当前线程之前acquire。
     * 同样，由于该队列为空，在该方法返回false后，另一个线程也可能赢得竞争，进入队列。
     *
     * <p>这种方法被设计用于公平同步器，以避免barging。
     * 这样一个同步器的tryAcquire方法应该返回false，
     * 如果这个方法返回true，tryAcquireShared方法应该返回一个负值(除非这是一个可重入的获取)。
     * 例如，一个公平的、可重入的、独占的模式同步器的tryAcquire方法可能是这样的:
     *
     *  <pre> {@code
     * protected boolean tryAcquire(int arg) {
     *   if (isHeldExclusively()) {
     *     // A reentrant acquire; increment hold count
     *     return true;
     *   } else if (hasQueuedPredecessors()) {
     *     return false;
     *   } else {
     *     // try to acquire normally
     *   }
     * }}</pre>
     *
     * @return {@code true} if there is a queued thread preceding the
     *         current thread, and {@code false} if the current thread
     *         is at the head of the queue or the queue is empty
     * @since 1.7
     */
    public final boolean hasQueuedPredecessors() {
        // 它的正确性取决于head在tail之前被初始化，
    	// 和如果当前线程是队列中的第一个，则head.next是准确的。
        Node t = tail; // 按照反向初始化顺序读取字段
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }


    // 仪器和监测方法

    /**
     * 返回等待获取的线程数的估计数。
     * 这个值只是一个估计值，因为在这个方法遍历内部数据结构时，线程数可能会动态改变。
     * 此方法设计用于监控系统状态，而不是用于同步控制。
     *
     * @return the estimated number of threads waiting to acquire
     */
    public final int getQueueLength() {
        int n = 0;
        for (Node p = tail; p != null; p = p.prev) {
            if (p.thread != null)
                ++n;
        }
        return n;
    }

    /**
     * 返回一个包含可能正在等待获取的线程的集合。
     * 因为实际的线程集可能会在构造这个结果时动态改变，所以返回的collection只是一个最佳效果的估计。
     * 返回集合的元素没有特定的顺序。
     * 这种方法的设计是为了方便构造提供更广泛监控设施的子类。
     *
     * @return the collection of threads
     */
    public final Collection<Thread> getQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node p = tail; p != null; p = p.prev) {
            Thread t = p.thread;
            if (t != null)
                list.add(t);
        }
        return list;
    }

    /**
     * 返回一个集合，其中包含可能正在等待以独占模式获取的线程。
     * 它具有与getQueuedThreads相同的属性，只是它只返回那些由于独占获取而等待的线程。
     *
     * @return the collection of threads
     */
    public final Collection<Thread> getExclusiveQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node p = tail; p != null; p = p.prev) {
            if (!p.isShared()) {
                Thread t = p.thread;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }

    /**
     * 返回一个包含可能在共享模式下等待获取的线程的集合。
     * 它具有与getQueuedThreads相同的属性，只是它只返回那些由于共享获取而等待的线程。
     *
     * @return the collection of threads
     */
    public final Collection<Thread> getSharedQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node p = tail; p != null; p = p.prev) {
            if (p.isShared()) {
                Thread t = p.thread;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }

    /**
     * 返回标识此同步器及其状态的字符串。
     * 方括号中的state包含字符串" state ="，后面跟着getState的当前值，
     * 以及"nonempty"或"empty"，这取决于队列是否为空。
     *
     * @return a string identifying this synchronizer, as well as its state
     */
    public String toString() {
        int s = getState();
        String q  = hasQueuedThreads() ? "non" : "";
        return super.toString() +
            "[State = " + s + ", " + q + "empty queue]";
    }


    // 内部支撑方法为条件

    /**
     * 如果一个节点(总是最初放置在条件队列中的节点)
     * 现在正在同步队列上等待重新获取，则返回true。
     * 
     * @param node the node
     * @return true if is reacquiring
     */
    final boolean isOnSyncQueue(Node node) {
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        if (node.next != null) // 如果有继承者，它必须在队列中
            return true;
        /*
         * node.prev可以是非空的，但还没有在队列中，
         * 因为将它放在队列中的CAS可能会失败。所以我们必须从尾巴开始，确保它真的成功了。
         * 在对该方法的调用中，它总是靠近尾部，除非CAS失败(这是不太可能的)，
         * 否则它就会在那里，因此我们几乎不会遍历太多。
         */
        return findNodeFromTail(node);
    }

    /**
     * 如果节点处于同步队列中，则通过从tail向后搜索返回true。仅在isOnSyncQueue需要时调用。
     * 
     * @return true if present
     */
    private boolean findNodeFromTail(Node node) {
        Node t = tail;
        for (;;) {
            if (t == node)
                return true;
            if (t == null)
                return false;
            t = t.prev;
        }
    }

    /**
     * 将节点从条件队列转移到同步队列。如果成功返回true。
     * 
     * @param node the node
     * @return true if successfully transferred (else the node was
     * cancelled before signal)
     */
    final boolean transferForSignal(Node node) {
        /*
         * 如果不能waitStatus不为condition，表示该节点已经取消。
         */
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;

        /*
         * 拼接到queue上并尝试设置前驱的waitStatus以指示线程(可能)正在等待。
         * 如果被取消或试图设置waitStatus失败，唤醒重新同步(在这种情况下，waitStatus可能是暂时的和无害的错误)。
         */
        Node p = enq(node);
        int ws = p.waitStatus;
        // p是node的前驱，设置p的状态为signal
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

    /**
     * 传输节点，如果有必要，在取消等待后同步队列。
     * 如果线程在被通知之前被取消（超出了时间限制或者被中断），则返回true。
     *
     * @param node the node
     * @return true if cancelled before the node was signalled
     */
    final boolean transferAfterCancelledWait(Node node) {
        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
            enq(node);
            return true;
        }
        /*
         * 如果我们输给了signal()，那么我们就不能继续，直到它完成它的enq()。
         * 在不完全转移过程中取消是罕见的，也是短暂的，所以只管旋转。
         */
        while (!isOnSyncQueue(node))
            Thread.yield();
        return false;
    }

    /**
     * 使用当前状态值调用release;
     * 返回保存的状态。
     * 取消节点并在失败时抛出异常。
     * 
     * @param node the condition node for this wait
     * @return previous sync state
     */
    final int fullyRelease(Node node) {
        boolean failed = true;
        try {
            int savedState = getState();
            if (release(savedState)) {
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

    // 条件测量方法

    /**
     * 查询给定的条件对象是否使用此同步器作为其锁。
     *
     * @param condition the condition
     * @return {@code true} if owned
     * @throws NullPointerException if the condition is null
     */
    public final boolean owns(ConditionObject condition) {
        return condition.isOwnedBy(this);
    }

    /**
     * 查询是否有线程正在等待与此同步器关联的给定条件。
     * 请注意，因为超时和中断可能在任何时候发生，
     * 返回true并不保证将来的信号会唤醒任何线程。该方法主要用于监控系统状态。
     *
     * @param condition the condition
     * @return {@code true} if there are any waiting threads
     * @throws IllegalMonitorStateException if exclusive synchronization
     *         is not held
     * @throws IllegalArgumentException if the given condition is
     *         not associated with this synchronizer
     * @throws NullPointerException if the condition is null
     */
    public final boolean hasWaiters(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.hasWaiters();
    }

    /**
     * 返回等待与此同步器相关的给定条件的线程数的估计数。
     * 请注意，因为超时和中断可能在任何时候发生，所以这个估计值仅作为实际等待者数量的上限。
     * 这种方法是设计用于监控系统状态，而不是用于同步控制。
     *
     * @param condition the condition
     * @return the estimated number of waiting threads
     * @throws IllegalMonitorStateException if exclusive synchronization
     *         is not held
     * @throws IllegalArgumentException if the given condition is
     *         not associated with this synchronizer
     * @throws NullPointerException if the condition is null
     */
    public final int getWaitQueueLength(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.getWaitQueueLength();
    }

    /**
     * 返回一个集合，其中包含可能正在等待与此同步器关联的给定条件的线程。
     * 因为实际的线程集可能会在构造这个结果时动态改变，所以返回的collection只是一个最佳效果的估计。
     * 返回集合的元素没有特定的顺序。
     *
     * @param condition the condition
     * @return the collection of threads
     * @throws IllegalMonitorStateException if exclusive synchronization
     *         is not held
     * @throws IllegalArgumentException if the given condition is
     *         not associated with this synchronizer
     * @throws NullPointerException if the condition is null
     */
    public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.getWaitingThreads();
    }

    /**
     * 作为锁实现基础的AbstractQueuedSynchronizer的条件实现。
     *
     * <p>这个类的方法文档从锁和条件的用户的角度描述了机制，而不是行为规范。
     * 该类的导出版本通常需要附带描述条件语义的文档，这些语义依赖于相关的AbstractQueuedSynchronizer的语义。
     *
     * <p>这个类是可序列化的，但是所有字段都是暂态的，因此反序列化的条件没有等待者。
     * 
     * 每一个Condition对象都对应到一个条件队列condition queue，而每个线程在执行await()后，都会被包装成一个node放到condition queue中去。
     * 
     * condition queue是一个单向链表，它使用nextWaiter作为链接。
     * 这个队列中，不存在dummy node，每个节点都代表一个线程。这个队列的节点的状态，我们只关心状态是否为CONDITION，
     * 如果是CONDITION的，说明线程还等待在这个Condition对象上；
     * 如果不是CONDITION的，说明这个节点已经前往sync queue了。
     * 
     * 假设现在存在一个Lock对象和通过这个Lock对象生成的若干个Condition对象，
     * 从队列上来说，就存在了一个sync queue和若干个与这个sync queue关联的condition queue。
     * 本来这两种队列上的节点没有关系，但现在有了signal方法，就会使得condition queue上的节点会跑到sync queue上去。
     * 
     * sync queue          null(head)  wait1  wait2  waitn(old tail) waitA(new tail)
     * condition queue  waitA(old firstWaiter)  waitB(new firstWaiter)  waitC   waitZ(lastWaiter)
     * 
     * 上图简单体现了节点从从condition queue转移到sync queue上去的过程。
     * 即使是调用signalAll时，节点也是一个一个转移过去的，因为每个节点都需要重新建立sync queue的链接。
     * 我们这里可以先简单理解一下关于队列的动作：
     * 
     * 如果一个节点刚入队sync queue，说明这个节点的代表线程没有获得锁（尝试获得锁失败了）。
     * 如果一个节点刚出队sync queue（指该节点的代表线程不在同步队列中的任何节点上，
     * 因为它已经跑到了AQS的exclusiveOwnerThread成员上去了），说明这个节点的代表线程刚获得了锁（尝试获得锁成功了）。
     * 如果一个节点刚入队condition queue，说明这个节点的代表线程此时是有锁了，但即将释放。
     * 如果一个节点刚出队condition queue，因为前往的是sync queue，说明这个节点的代表线程此时是没有获得锁的。
     * 
     * ConditionObject又是AQS的一个成员内部类，这意味着不管生成了多少个ConditionObject，
     * 它们都持有同一个AQS对象的引用，这和“一个Lock可以对应到多个Condition”相吻合。
     * 
     * 这也意味着：对于同一个AQS来说，只存在一个同步队列sync queue，但可以存在多个条件队列condition queue。
     * 成员内部类有一个好处，不管哪个ConditionObject对象都可以调到同一个外部类AQS对象的方法上去。
     * 比如acquireQueued方法，这样，不管node在哪个condition queue上，最终它们离开后将要前往的地方总是同一个sync queue。
     * 
     * 执行await的当前线程。这个线程是最开始调用await的线程，也是执行await所有调用链的线程，它被包装进局部变量node中。（后面会以node线程来称呼它）
     * 
     * 执行signal的线程。这个线程会改变await当前线程的node的状态state，使得await当前线程的node前往同步队列，并在一定条件在唤醒await当前线程。
     * 
     * 中断await当前线程的线程。你就当这个线程只是用来唤醒await当前线程，并改变其中断状态。
     * 只不过await当前线程它自己被唤醒后，也会做和上一条同样的事情：“使得await当前线程的node前往同步队列”。
     * 
     * 执行unlock的线程。如果await当前线程的node已经是同步队列的head后继，那么获得独占锁的线程在释放锁时，就会唤醒 await当前线程。
     * 理解了这几个线程的存在，对于本文的理解有很大帮助。从用户角度来说，执行await \ signal \ unlock的前提都是线程必须已经获得了锁。
     */
    public class ConditionObject implements Condition, java.io.Serializable {
        private static final long serialVersionUID = 1173984872572414699L;
        /** 条件队列的第一个节点。 
         * 
         * firstWaiter和lastWaiter分别代表条件队列的队头和队尾。
         * 注意，firstWaiter和lastWaiter都不再需要加volatile来保证可见性了。
         * 这是因为源码作者是考虑，使用者肯定是以获得锁的前提下来调用await() / signal()这些方法的，既然有了这个前提，
         * 那么对firstWaiter的读写肯定是无竞争的，既然没有竞争也就不需要 CAS+volatile 来实现一个乐观锁了。
         * */
        private transient Node firstWaiter;
        /** 条件队列的最后一个节点。*/
        private transient Node lastWaiter;

        /**
         * 创建一个新的条件对象实例。
         */
        public ConditionObject() { }

        // Internal methods

        /**
         * 增加了一个新的等待者到等待队列。
         * 
         * 同步队列sync queue的新建node，它的初始状态为0。而条件队列condition queue的新建node的初始状态为CONDITION。
         * sync queue如果拥有队头，队头肯定会是一个dummy node（即线程成员为null）。condition queue则不会有一个dummy node，每个节点的线程成员都不为null。
         * sync queue是一个双向链表，需要维持前驱和后继都正确。condition queue只是一个单链表，只需要维持后继即可。
         * 这里先提前说下，中断await当前线程的线程（这里特指中断操作在signal之前）和执行signal的线程都会使得条件队列上的node的状态从CONDITION变成0。
         * 
         * @return its new wait node
         */
        private Node addConditionWaiter() {
            Node t = lastWaiter;
            // 同步队列中的节点只是CONDITION的，如果不是，就认为是以后将离开条件队列的节点。
            // 将调用unlinkCancelledWaiters来一次大清理，并重新获得队尾
            if (t != null && t.waitStatus != Node.CONDITION) {
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
            // 包装当前线程为node，状态初始为CONDITION
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            //node放到最后
            if (t == null)// 如果当前队尾为null，那么整个条件队列都没初始化呢
                firstWaiter = node;
            else// 如果队列有至少一个节点
                t.nextWaiter = node;
            lastWaiter = node;
            return node;
        }

        /**
         * 删除和传输节点，直到命中非取消的节点或null。
         * 从signal中分离出来部分是为了鼓励编译器，关联没有等待者的情况。
         * 
         * @param first (non-null) the first node on condition queue
         */
        private void doSignal(Node first) {
            do {
            	// 先把firstWaiter变成first.nextWaiter
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
                // 将first从条件队列转移到同步队列，如果失败，first=firstWaiter，继续循环，知道firstWaiter为null
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }

        /**
         * 删除和传输所有节点。
         * 
         * @param first (non-null) the first node on condition queue
         */
        private void doSignalAll(Node first) {
            lastWaiter = firstWaiter = null;
            do {
                Node next = first.nextWaiter;
                first.nextWaiter = null;
                // 逐个传输
                transferForSignal(first);
                first = next;
            } while (first != null);
        }

        /**
         * unlinkCancelledWaiters函数是用来从头到尾清理状态不为CONDITION的节点的。
         * 
         * 从条件队列中解除被取消的等待节点（等待的时候被中断）的链接。仅在持有锁时调用。
         * 当在条件等待期间发生取消时，以及当看到最后一个等待者被取消时插入一个新的等待者时，就会调用这个函数。
         * 这个方法是为了避免在没有信号的情况下垃圾保留。
         * 因此，即使它可能需要一次完整的遍历，它也只有在没有信号的情况下出现超时或取消时才会发挥作用。
         * 它遍历所有节点，而不是在特定目标处停止，以解除指向垃圾节点的所有指针的链接，而不需要在取消风暴期间多次重新遍历。
         */
        private void unlinkCancelledWaiters() {
            Node t = firstWaiter;
            Node trail = null;
            while (t != null) {
                Node next = t.nextWaiter;
                if (t.waitStatus != Node.CONDITION) {
                	// 在condition队列中删除t，如果t的状态不是condition
                    t.nextWaiter = null;
                    if (trail == null)
                        firstWaiter = next;
                    else
                        trail.nextWaiter = next;
                    if (next == null)
                        lastWaiter = trail;
                }
                else
                    trail = t;
                t = next;
            }
        }

        // public methods

        /**
         * 将等待时间最长的线程(如果存在的话)
         * 从这种情况的等待队列移动到所属锁的等待队列。
         *
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        public final void signal() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignal(first);
        }

        /**
         * 将此情况下的所有线程从等待队列移动到所属锁的等待队列。
         *
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        public final void signalAll() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignalAll(first);
        }

        /**
         * 实现不可中断条件等待。
         * <ol>
         * <li> 保存getState返回的锁状态。
         * <li> 以保存的状态作为参数调用release，如果失败则抛出IllegalMonitorStateException。
         * <li> 阻塞直到被signal
         * <li> 通过调用特定版本的acquire，并将保存的状态作为参数进行重新获取。
         * </ol>
         */
        public final void awaitUninterruptibly() {
        	// condition队列中添加节点
            Node node = addConditionWaiter();
            // 释放锁，解锁head的后驱的 线程
            int savedState = fullyRelease(node);
            boolean interrupted = false;
            // 如果node不在同步队列上，阻塞node
            // 直到有人signal该节点，将节点从condition队列放到同步队列，跳出循环
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                if (Thread.interrupted())
                    interrupted = true;
            }
            // 以独占不可中断模式获取已经在队列中的线程。用于条件等待方法和acquire方法。
            if (acquireQueued(node, savedState) || interrupted)
                selfInterrupt();
        }

        /*
         * 对于可中断等待，我们需要跟踪是否抛出InterruptedException，
         * 如果在条件阻塞时被中断，而如果在阻塞等待重新获取时被中断，则重新中断当前线程。
         */

        /** 模式意味着退出等待时重新中断 */
        private static final int REINTERRUPT =  1;
        /** 模式表示在退出等待时抛出InterruptedException */
        private static final int THROW_IE    = -1;

        /**
         * 检查中断，如果在被通知之前被中断返回THROW_IE，
         * 如果被通知之后重新中断，或者如果没有被中断返回0。
         */
        private int checkInterruptWhileWaiting(Node node) {
            return Thread.interrupted() ?
                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                0;
        }

        /**
         * Throws InterruptedException, reinterrupts current thread, or
         * does nothing, depending on mode.
         */
        private void reportInterruptAfterWait(int interruptMode)
            throws InterruptedException {
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }

        /**
         * 实现可中断条件等待。
         * <ol>
         * <li> 如果当前线程被中断，则抛出InterruptedException。
         * <li> 保存getState返回的锁状态。
         * <li> 以保存的状态作为参数调用release，如果失败则抛出IllegalMonitorStateException。
         * <li> 阻塞直到被signal或者被中断
         * <li> 通过调用特定版本的acquire，并将保存的状态作为参数进行重新获取。
         * <li> 如果在步骤4中阻塞时被中断，则抛出InterruptedException。
         * </ol>
         */
        public final void await() throws InterruptedException {
        	// 在调用await之前，当前线程就已经被中断了，那么抛出异常
            if (Thread.interrupted())
                throw new InterruptedException();
            // 将当前线程包装进Node,然后放入当前Condition的条件队列
            Node node = addConditionWaiter();
            // 释放锁，不管当前线程重入锁多少次，都要释放干净
            int savedState = fullyRelease(node);
            int interruptMode = 0;
            // 如果当前线程node不在同步队列上，说明还没有别的线程调用 当前Condition的signal。
            // 第一次进入该循环，肯定会符合循环条件，然后park阻塞在这里
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                // 如果被中断了，跳出等待被signal的循环，并调用transferAfterCancelledWait，节点从condition队列放到同步队列，跳出循环
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // 如果被取消，进行清理，transferAfterCancelledWait没有清理nextWaiter
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }

        /**
         * 实现有时间限制的条件等待。
         * <ol>
         * <li> 如果当前线程被中断，则抛出InterruptedException。
         * <li> 保存getState返回的锁状态。
         * <li> 以保存的状态作为参数调用release，如果失败则抛出IllegalMonitorStateException。
         * <li> 阻塞直到被signal或者被中断或者时间到了
         * <li> 通过调用特定版本的acquire，并将保存的状态作为参数进行重新获取。
         * <li> 如果在步骤4中阻塞时被中断，则抛出InterruptedException。
         * </ol>
         */
        public final long awaitNanos(long nanosTimeout)
                throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            final long deadline = System.nanoTime() + nanosTimeout;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
            	// 如果超出了时间限制，节点状态从condition变成0，节点加入同步节点
                if (nanosTimeout <= 0L) {
                    transferAfterCancelledWait(node);
                    break;
                }
                // 如果时间还够，线程阻塞
                if (nanosTimeout >= spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                // 如果被中断，节点状态从condition变成0，节点加入同步节点
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
                nanosTimeout = deadline - System.nanoTime();
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
            	// 如果被取消，进行清理，transferAfterCancelledWait没有清理nextWaiter
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return deadline - System.nanoTime();
        }

        /**
         * Implements absolute timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with saved state as argument,
         *      throwing IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.
         * <li> Reacquire by invoking specialized version of
         *      {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * <li> If timed out while blocked in step 4, return false, else true.
         * </ol>
         */
        public final boolean awaitUntil(Date deadline)
                throws InterruptedException {
            long abstime = deadline.getTime();
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (System.currentTimeMillis() > abstime) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                LockSupport.parkUntil(this, abstime);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        /**
         * Implements timed condition wait.
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * <li> Save lock state returned by {@link #getState}.
         * <li> Invoke {@link #release} with saved state as argument,
         *      throwing IllegalMonitorStateException if it fails.
         * <li> Block until signalled, interrupted, or timed out.
         * <li> Reacquire by invoking specialized version of
         *      {@link #acquire} with saved state as argument.
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * <li> If timed out while blocked in step 4, return false, else true.
         * </ol>
         */
        public final boolean await(long time, TimeUnit unit)
                throws InterruptedException {
            long nanosTimeout = unit.toNanos(time);
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            final long deadline = System.nanoTime() + nanosTimeout;
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (nanosTimeout <= 0L) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                if (nanosTimeout >= spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
                nanosTimeout = deadline - System.nanoTime();
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        //  支持工具

        /**
         * 如果此条件是由给定的同步对象创建的，则返回true。
         *
         * @return {@code true} if owned
         */
        final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
            return sync == AbstractQueuedSynchronizer.this;
        }

        /**
         * 查询是否有线程正在等待此条件。
         * 实现AbstractQueuedSynchronizer.hasWaiters (ConditionObject)。
         *
         * @return {@code true} if there are any waiting threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        protected final boolean hasWaiters() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    return true;
            }
            return false;
        }

        /**
         * 返回等待此条件的线程数的估计数。
         * 实现AbstractQueuedSynchronizer.getWaitQueueLength (ConditionObject)。
         *
         * @return the estimated number of waiting threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        protected final int getWaitQueueLength() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int n = 0;
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    ++n;
            }
            return n;
        }

        /**
         * 返回一个集合，其中包含可能正在等待此条件的线程。
         * 实现AbstractQueuedSynchronizer.getWaitingThreads (ConditionObject)。
         *
         * @return the collection of threads
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
         *         returns {@code false}
         */
        protected final Collection<Thread> getWaitingThreads() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION) {
                    Thread t = w.thread;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }
    }

    /**
     * 设置以支持compareAndSet。
     * 我们需要在这里本机实现这个:为了允许未来的增强，我们不能显式地子类化AtomicInteger，否则这将是高效和有用的。
     * 因此，为了解决这个问题，我们使用了hotspot intrinsics API。
     * 当我们这样做的时候，我们对其他CASable字段做同样的事情(否则可以用原子字段更新器来做)。
     * 
     * 需要通过CAS操作来修改的属性有AQS的state、head和tail；Node的waitStatus和next。因为这几个属性确实会被多线程访问。
     * 最后，我们利用Unsafe的compareAndSetXXX即CAS方法。
     */
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long stateOffset;
    private static final long headOffset;
    private static final long tailOffset;
    private static final long waitStatusOffset;
    private static final long nextOffset;

    static {
        try {
            stateOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
            headOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
            tailOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
            waitStatusOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("waitStatus"));
            nextOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("next"));

        } catch (Exception ex) { throw new Error(ex); }
    }

    /**
     * 仅仅被enq方法使用，CAS修改head字段
     */
    private final boolean compareAndSetHead(Node update) {
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }

    /**
     * 仅仅被enq方法使用，CAS修改tail字段
     */
    private final boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

    /**
     * CAS修改一个节点的waitStatus字段
     */
    private static final boolean compareAndSetWaitStatus(Node node,
                                                         int expect,
                                                         int update) {
        return unsafe.compareAndSwapInt(node, waitStatusOffset,
                                        expect, update);
    }

    /**
     * CAS修改一个节点的next字段
     */
    private static final boolean compareAndSetNext(Node node,
                                                   Node expect,
                                                   Node update) {
        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
    }
}
